//------------------------------------------------------------------------------
// <copyright company="Telligent Systems">
//     Copyright (c) Telligent Systems Corporation.  All rights reserved.
// </copyright> 
//------------------------------------------------------------------------------

using System;
using System.Collections;
using System.Collections.Specialized;
using System.Text;
using CommunityServer.Components;

namespace CommunityServer.Components
{
	/// <summary>
	/// Summary description for SearchProvider.
	/// </summary>
	public abstract class SearchProvider
	{
		#region internal
		private static readonly SearchProvider _instance = null;
		static SearchProvider()
		{
			_instance = SingletonProviderHelper.LoadInstance("SearchProvider",null) as SearchProvider;
		}
		#endregion


		public static SearchProvider Instance()
		{
			if(_instance == null)
				throw new CSException(CSExceptionType.UnKnownProvider, "The provider for SearchProvider could not be loaded");


			return _instance;
		}

		public abstract SearchResultSet Search(SearchQuery query);
		
		public virtual string SearchQueryString(SearchQuery query)
		{
			StringBuilder sb = new StringBuilder();

			if (!Globals.IsNullorEmpty(query.QueryText))
			{
				sb.Append("q=");
				sb.Append(Globals.UrlEncode(query.QueryText));
			}

			if ((query.UserNamesToSearch != null && query.UserNamesToSearch.Length > 0) || (query.UsersToSearch != null && query.UsersToSearch.Length > 0))
			{
				if (sb.Length > 0)
					sb.Append("&");

				sb.Append("u=");
				bool isFirst = true;

				if (query.UserNamesToSearch != null && query.UserNamesToSearch.Length > 0)
				{
					for (int i = 0; i < query.UserNamesToSearch.Length; i++)
					{
						try
						{
							User user = CommunityServer.Users.FindUserByUsername(query.UserNamesToSearch[i].TrimStart(' ').TrimEnd(' '));
							if (user.UserID > -1)
							{
							
								if (isFirst)
									isFirst = false;
								else
									sb.Append(",");

								sb.Append(user.UserID.ToString());
							}
						}
						catch
						{
						}
					}
				}

				if (query.UsersToSearch != null && query.UsersToSearch.Length > 0)
				{
					for (int i = 0; i < query.UsersToSearch.Length; i++)
					{
						if (isFirst)
							isFirst = false;
						else
							sb.Append(",");

						sb.Append(query.UsersToSearch[i].ToString());
					}
				}
			}

			if (query.ApplicationTypes != null && query.ApplicationTypes.Length > 0)
			{
				if (sb.Length > 0)
					sb.Append("&");

				sb.Append("a=");

				for (int i = 0; i < query.ApplicationTypes.Length; i++)
				{
					if (i > 0)
						sb.Append(",");

					sb.Append(((int) query.ApplicationTypes[i]).ToString());
				}
			}

			if (query.GroupsToSearch != null && query.GroupsToSearch.Length > 0)
			{
				if (sb.Length > 0)
					sb.Append("&");

				sb.Append("g=");
				
				for (int i = 0; i < query.GroupsToSearch.Length; i++)
				{
					if (i > 0)
						sb.Append(",");

					sb.Append(query.GroupsToSearch[i].ToString());
				}
			}

			if (query.SectionsToSearch != null && query.SectionsToSearch.Length > 0)
			{
				if (sb.Length > 0)
					sb.Append("&");

				sb.Append("s=");

				for (int i = 0; i < query.SectionsToSearch.Length; i++)
				{
					if (i > 0)
						sb.Append(",");

					sb.Append(query.SectionsToSearch[i].ToString());
				}
			}

			if (query.SortBy != SearchSort.Relevance)
			{
				if (sb.Length > 0)
					sb.Append("&");

				sb.Append("o=");
				sb.Append(Globals.UrlEncode(query.SortBy.ToString()));
			}

			if (query.StartDate != DateTime.MinValue)
			{
				if (sb.Length > 0)
					sb.Append("&");

				sb.Append("sd=");
				sb.Append(Globals.UrlEncode(query.StartDate.ToShortDateString()));
			}

			if (query.EndDate != DateTime.MinValue)
			{
				if (sb.Length > 0)
					sb.Append("&");

				sb.Append("ed=");
				sb.Append(Globals.UrlEncode(query.EndDate.ToShortDateString()));
			}

			if (query.HasTags)
			{
				if (sb.Length > 0)
					sb.Append("&");

				sb.Append("tag=");
				for (int i = 0; i < query.Tags.Length; i++)
				{
					if (i > 0)
						sb.Append(",");

					sb.Append(Globals.UrlEncode(query.Tags[i]));
				}

				sb.Append("&orTags=");
				sb.Append(query.LogicallyOrTags ? "1" : "0");
			}

			return sb.ToString();
		}
        
		public virtual SearchQuery GetSearchQueryFromQueryString(NameValueCollection queryString)
		{
            SearchQuery query = new SearchQuery();

			string keyWords = queryString["q"] == null ? String.Empty : queryString["q"];
			string usersList = queryString["u"] == null ? String.Empty : queryString["u"];
			string applicationList = queryString["a"] == null ? String.Empty : queryString["a"];
			string groupList = queryString["g"] == null ? String.Empty : queryString["g"];
            string sectionList = queryString["s"] == null ? String.Empty : queryString["s"];
            string tagList = queryString["tag"] == null ? String.Empty : queryString["tag"];
			string orTags = queryString["orTags"] == null ? String.Empty : queryString["orTags"];
            
            DateTime startDate = DateTime.MinValue;
            DateTime endDate = DateTime.MinValue;
            SearchSort searchSort = SearchSort.Relevance;

            if(!Globals.IsNullorEmpty(queryString["sd"]))
            {
                try
                {
                    startDate= DateTime.Parse(queryString["sd"]);
                }
                catch{}
            }

            if(!Globals.IsNullorEmpty(queryString["ed"]))
            {
                try
                {
                    endDate= DateTime.Parse(queryString["ed"]);
                }
                catch{}
            }

            if(!Globals.IsNullorEmpty(queryString["o"]))
            {
                try
                {
                    searchSort = (SearchSort) Enum.Parse(typeof(SearchSort), queryString["o"],true); 
                }
                catch{}
            }
                

			
			
			query.QueryText = keyWords;
			
			#region Parse user list

			if (!Globals.IsNullorEmpty(usersList))
			{
				string[] users = usersList.Split(',');
				int[] userIds = new int[users.Length];
				for (int i = 0; i < users.Length; i++)
					userIds[i] = int.Parse(users[i]);

				query.UsersToSearch = userIds;
			}

			#endregion

			#region Parse application/group/section lists

			
			ArrayList applicationTypes = new ArrayList();
			if (!Globals.IsNullorEmpty(applicationList))
			{
				foreach (string appId in applicationList.Split(','))
				{
					applicationTypes.Add((ApplicationType) int.Parse(appId));
				}
			}

			if (applicationTypes.Count > 0)
				query.ApplicationTypes = (ApplicationType[]) applicationTypes.ToArray(typeof(ApplicationType));

            ArrayList tags = new ArrayList();
            if (!Globals.IsNullorEmpty(tagList))
            {
                foreach (string tag in tagList.Split(','))
                {
                    tags.Add(tag);
                }

				if (orTags != string.Empty)
					query.LogicallyOrTags = orTags == "1";
            }

            if (tags.Count > 0)
                query.Tags = (string[])tags.ToArray(typeof(string));

			ArrayList groupIds = new ArrayList();
			if (!Globals.IsNullorEmpty(groupList))
			{
				foreach (string groupId in groupList.Split(','))
				{
					groupIds.Add(int.Parse(groupId));
				}
			}

			if (groupIds.Count > 0)
				query.GroupsToSearch = (int[]) groupIds.ToArray(typeof(int));

			ArrayList sectionIds = new ArrayList();
			if (!Globals.IsNullorEmpty(sectionList))
			{
				foreach (string sectionId in sectionList.Split(','))
				{
					sectionIds.Add(int.Parse(sectionId));
				}
			}

			if (sectionIds.Count > 0)
				query.SectionsToSearch = (int[]) sectionIds.ToArray(typeof(int));

			#endregion

			#region Process start/end dates

			if (startDate != DateTime.MinValue)
			{
				query.StartDate = startDate;
				if (endDate != DateTime.MinValue)
					query.EndDate = endDate;
				else
					query.EndDate = startDate;
			}

			#endregion

			query.SortBy = searchSort;

			return query;
		}
   
	}


    public class SearchForm
    {
        public string[] Sections;
        public string[] Groups;
        public string[] Users;
        public string[] Applications;
        public string[] Categories;
        public string QueryText;
        public DateTime StartDate;
        public DateTime EndDate;
        public SearchSort Sort = SearchSort.Relevance;

    }




}
